/* s2 - compare values, considering some Spectre issues
   Copyright (C) 2018, 2019 Ariadne Devos

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */

/* This is transcluded from <sHT/test.h> */

#if defined(__x86_64__) || defined(__i386__)

/* Operand order: first the source, then the destination.
  E.g., cmp $3,%rdx.

  When compiling, the following diagnostic was print:
  > Error: too many memory references for cmp
  Use the alternative constraints feature of GCC to
  avoid this problem.

  When reading AMD and probably Intel documentation:
  'greater' is for signed integers, 'above' for unsigned integers. */

# define _sHT_ge(a, b, correct) \
	__asm__ goto ("cmp %1,%0;jae %l[" #correct "]" : : "r,m" (a), "rmi,ri" (b) : "cc" : correct)
# define _sHT_eq(a, b, correct) \
	__asm__ goto ("cmp %1,%0;je %l[" #correct "]" : : "r,m" (a), "rmi,ri" (b) : "cc" : correct)
# define _sHT_neq(a, b, correct) \
	__asm__ goto ("cmp %1,%0;jne %l[" #correct "]" : : "r,m" (a), "rmi,ri" (b) : "cc" : correct)
# define _sHT_eq_bool(a, b, c) \
	__asm__ ("cmp %2,%1;sete %0" : "=r,r" (c) : "r,m" (a), "rmi,ri" (b) : )


# define _sHT_gt(a, b, correct) \
	__asm__ goto ("cmp %1,%0;ja %l[" #correct "]" : : "r,m" (a), "rmi,ri" (b) : "cc" : correct)

/* testl is supposedlu smaller than cmp */
# define _sHT_zero_p(a, correct) \
	__asm__ goto ("test %0,%0;je %l[" #correct "]" : : "r" (a) : "cc" : correct)
# define _sHT_nonzero_p(a, correct) \
	__asm__ goto ("test %0,%0;jnz %l[" #correct "]" : : "r" (a) : "cc" : correct)
# define _sHT_lt0(a, correct) \
	__asm__ goto ("test %0,%0;js %l[" #correct "]" : : "r" (a) : "cc" : correct)
#define _sHT_and_any_p(a, b, correct) \
	__asm__ goto ("test %1,%0;jnz %l[" #correct "]" : : "r,m" (a), "rmi,ri" (b) : "cc" : correct)
#define _sHT_and_none_p(a, b, correct) \
	__asm__ goto ("test %1,%0;je %l[" #correct "]" : : "r,m" (a), "rmi,ri" (b) : "cc" : correct)

#else
# error unsupported architecture, should be easy
#endif
